<template>
  <view
    class="form-item"
    :class="[
      {
        'form-item--error': !!errorMessage,
        'form-item--required': getRequired,
        'form-item--has-label': getLabelWidth > 0,
        'form-item--inset': inset,
        'form-item--border': getBorder,
      },
    ]"
    :style="[getStyle]"
  >
    <view class="form-item__label" :style="[getLabelStyle]">
      <slot v-if="$slots.label" name="label" />
      <m-text v-else :line="1" :bold="labelBold"> {{ label }} </m-text>
    </view>
    <view class="form-item__field">
      <view class="form-item__cell">
        <view class="form-item__cell__center">
          <slot />
        </view>
        <view class="form-item__cell__right"> <slot name="right" /> </view>
      </view>
      <view class="form-item__error-msg">
        {{ errorMessage }}
      </view>
    </view>
  </view>
</template>

<script lang="ts">
import {
  defineComponent,
  onMounted,
  onUnmounted,
  inject,
  reactive,
  toRefs,
  computed,
  provide,
} from '@vue/composition-api'
import settings from '@/settings'
import addUnit from '@/utils/add-unit'

export default defineComponent({
  props: {
    label: {
      type: String,
      default: '',
    },
    prop: {
      type: String,
      default: '',
    },
    required: {
      type: Boolean,
      default: false,
    },
    labelWidth: {
      type: [Number, String],
      default: null,
    },
    labelBold: {
      type: [Boolean, Number],
      default: false,
    },
    inset: {
      type: [Boolean, Number],
      default: settings.css['--card-style'] === 'card',
    },
    border: {
      type: [Boolean, Number],
      default: null,
    },
    padding: {
      type: String,
      default: '28rpx 24rpx',
    },
  },
  options: {
    virtualHost: true, //  将自定义节点设置成虚拟的，更加接近Vue组件的表现。我们不希望自定义组件的这个节点本身可以设置样式、响应 flex 布局等，而是希望自定义组件内部的第一层节点能够响应 flex 布局或者样式由自定义组件本身完全决定
  },
  setup(props) {
    const formItemParent: any = inject('formItemParent', null)
    const cellParent: any = inject('cellParent', null)
    const state = reactive({
      errorMessage: '',
    })
    const setError = (errorMessage) => {
      state.errorMessage = errorMessage
    }
    const getRequired = computed(() => {
      if (props.required) {
        return true
      }

      const prop = props.prop

      if (!prop) {
        return false
      }

      const rule = formItemParent.rules[props.prop]

      if (!rule) {
        return false
      }

      if (Array.isArray(rule)) {
        return rule.some((x) => x.required)
      }

      return rule.required
    })
    const getLabelStyle = computed(() => {
      return { width: addUnit(getLabelWidth.value) }
    })
    const getBorder = computed(() => {
      if (props.border != null) {
        return props.border
      }

      if (cellParent) {
        return cellParent.border
      }

      return false
    })

    const getLabelWidth = computed(() => {
      if (props.labelWidth != null) {
        return props.labelWidth
      }

      if (formItemParent) {
        return formItemParent.labelWidth
      }

      return 152
    })

    const getStyle = computed(() => {
      return { padding: props.padding }
    })

    provide('formItem', {
      validate: () => {
        formItemParent.validateItem(props.prop)
      },
    })
    onMounted(async () => {
      if (formItemParent && formItemParent.addFormItem && props.prop) {
        formItemParent.addFormItem({
          prop: props.prop,
          vm: {
            setError,
          },
        })
      }
    })

    onUnmounted(async () => {
      if (formItemParent && formItemParent.removeFormItem && props.prop) {
        formItemParent.removeFormItem(props.prop)
      }
    })

    return {
      ...toRefs(state),
      getRequired,
      getLabelWidth,
      getLabelStyle,
      getBorder,
      getStyle,
    }
  },
})
</script>
<style lang="scss" scoped>
.form-item {
  display: flex;
  border-radius: 12rpx;
  background: #fff;
  position: relative;
  &::after {
    position: absolute;
    bottom: 0;
    left: 24rpx;
    right: 24rpx;
    border-bottom: 1rpx solid var(--ce);
  }
  &--border {
    &::after {
      content: '';
    }
  }
  &:last-child {
    &::after {
      display: none;
    }
  }
  &__label {
    font-size: 28rpx;
  }
  &__field {
    min-width: 0;
    flex: 1;
  }
  &__cell {
    display: flex;
    align-items: center;
    &__center {
      min-width: 0;
      flex: 1;
    }
    &__right {
      font-size: 28rpx;
      margin-left: 24rpx;
    }
  }
  &__error-msg {
    @include fz20;
    transform-origin: left center;
    color: red;
  }
  // &--required {
  //   &::before {
  //     position: absolute;
  //     left: 4rpx;
  //     color: $--primary-c;
  //     content: '*';
  //   }
  // }
  &--inset {
    margin-left: 24rpx;
    margin-right: 24rpx;
  }
  // &--error {
  //   &::after {
  //     border-bottom-color: red;
  //   }
  // }
}
</style>
